﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using sdd.utilities;

// SDD# - Software Defined Devices in C# for Linux and Windows
// Serial port support
// (c) 2014-2015 Chris Burri. MIT License applies. 
// See http://niston.wordpress.com

namespace sdd.subsystems.io
{
    public class SerialIOComPort : ISerialIO
    {
    #region Members Vars
        private string _PortName = "";
        private bool _portIsValid = false;
        private EnhancedSerialPort _ComPort;
    #endregion

    #region Constructor/Destructor
        public SerialIOComPort(string PortName)
        {
            _PortName = PortName;
        }

        ~SerialIOComPort()
        {
            _ComPort.DataReceived -= _ComPort_OnDataReceived;
        }
    #endregion

    #region Public Interface

        public event EventHandler DataReceived;

        private EnhancedSerialPort ComPort { get { return _ComPort; } }

        public string PortName
        {
            get { return _PortName; }
            set
            {
                if (_portIsValid)
                {
                    if (!_ComPort.IsOpen)
                    {
                        _PortName = value;
                    }
                    else
                    {
                        throw new System.IO.IOException("Can't change COM port name; Port is in use.");
                    }
                }
            }

        }

        public sdd.utilities.EnhancedSerialPort EnhancedSerialPort
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
            }
        }

        public void Open()
        {
            try
            {
                _ComPort = new EnhancedSerialPort(_PortName);
                _ComPort.BaudRate = 115200;
                _ComPort.Open();
                _ComPort.DataReceived += _ComPort_OnDataReceived;
                _portIsValid = true;
            }
            catch
            {
                _portIsValid = false;
            }
        }

        public void Close()
        {
            try
            {
                if (_portIsValid)
                {
                    if (_ComPort.IsOpen)
                    {
                        _ComPort.DataReceived -= _ComPort_OnDataReceived;
                        _ComPort.Close();
                    }
                }
            }
            catch
            {
                // error during close, there's nothing we could do
            }
        }

        public void Send(byte[] Command)
        {
            try
            {
                if (_ComPort != null)
                    if (_ComPort.IsOpen)
                        _ComPort.Write(Command, 0, Command.Length);
            }
            catch (System.IO.IOException)
            {
                System.Diagnostics.Debug.Assert(false);
            }
        }

        public void Send(string Text)
        {
            try
            {
                if (_ComPort != null)
                    if (_ComPort.IsOpen && !(string.IsNullOrEmpty(Text)))
                        _ComPort.Write(Text);
            }
            catch (System.IO.IOException)
            {
                System.Diagnostics.Debug.Assert(false);
            }
        }

        public string Read()
        {
            try
            {
                if (_ComPort != null)
                {
                    if (_ComPort.IsOpen)
                    {
                        return _ComPort.ReadExisting();
                    }
                    else
                    {
                        return "";
                    }
                }
                else
                {
                    return "";
                }
            }
            catch
            {
                // read failed
                return "";
            }
        }


    #endregion

    #region Private Functions
        void _ComPort_OnDataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            if (DataReceived != null) { DataReceived(this, new EventArgs()); }
        }
    #endregion

    }
}
